/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package mware_lib;

import java.io.IOException;
import mware_lib.Communicator.Server;

/**
 * @author Gortex
 */
public class ObjectBroker {

    private NameService ns;
    private String serviceHost;
    private int listenPort;
    private ReferenceModule referenceModule;
    private int startRequestPort = 9001;
    private ListenerThread listener;

    private ObjectBroker(String serviceHost, int listenPort) {
        this.serviceHost = serviceHost;
        this.listenPort = listenPort;
        this.referenceModule = new ReferenceModule();
    }

    /**
     * Das hier zurückgelieferte Objekt soll der zentrale Einstiegspunkt 
     * der Middleware aus Anwendersicht sein. 
     * Parameter: Host und Port, bei dem die Dienste (Namensdienst) kontaktiert werden sollen.
     */
    public static ObjectBroker init(String serviceHost, int listenPort) {
        ObjectBroker broker = new ObjectBroker(serviceHost, listenPort);
        broker.startTCPListener();
        return broker;
    }

    private void startTCPListener() {
        try {
            this.listener = new ListenerThread(new Server(startRequestPort), this);
            this.listener.start();
        } catch (IOException ex) {
            System.err.println("ObjectBroker startTCPListener - Port:" + startRequestPort + " belegt. Message: Versuch mit nächstem Port. ");
            this.startRequestPort += 1;
            this.startTCPListener();
        }
    }

    protected IBaseSkeleton getSkeletonByReference(String ref) {
        return referenceModule.getSkelletonForRef(ref);
    }

    // Liefert den Namensdienst (Stellvetreterobjekt).
    public NameService getNameService() {
        if (ns == null) {
            return new NameServiceProxy(serviceHost, listenPort, this);
        } else {
            return ns;
        }
    }

    /**
     * servant kann z.B. ein konto objekt sein, welches von der entsprechenden implbase 
     * erben muss (laut konventionen). das interface ihasskeleton(dass implementieren
     * alle implbase abstrakten klassen) stellt sicher, dass die methode generateskeleton 
     * auf dem richtigen objekt ausgeführt wird. diese liefert das zugehörige skeleton.
     * außerdem wird das skeleton auf dass konkrete objekt im entfernten referenzmodul abgebildet.
     * @param servant
     * @param name
     * @return 
     */
    protected String manageReferences(Object servant, String name) {
        String ref = referenceModule.generateReference(servant, startRequestPort);
        IHasSkelleton proxy = (IHasSkelleton) servant;
        IBaseSkeleton skeleton = proxy.generateSkeleton();
        referenceModule.register(ref, skeleton);
        return ref;
    }

    /**
     * Beendet die Benutzung der Middleware in dieser Anwendung.
     * veranlasst den listenerthread seine unterthread zu beenden, auf 
     * diese beendigung zu warten und dann sich selber zu beenden
     */
    public void shutDown() {
        System.out.println("ObjectBroker SHUTDOWN aufgerufen ");
        try {
            listener.interrupt();
            listener.shutDownSocket();
            listener.join();
        } catch (IOException ex) {
            System.out.println("ServerSocket beendet");
        } catch (InterruptedException ex) {
//           Thread.currentThread().interrupt();
        }
    }
}
